﻿using System.IO;
using System.Web;
using SlamCms.Common;

namespace SlamCms.SharePointServices
{
	public class SharePointImageService : SharePointServiceBase
	{
		private readonly HttpContextBase httpContext;

		public SharePointImageService(HttpContextBase httpContext)
		{
			this.httpContext = httpContext;
		}

		protected override string FolderVirtualPath
		{
			get
			{
				return "~/App_Data/Images/";
			}
		}

		public string RetrieveUrl(string url, int width = 0, int height = 0, bool crop = false, int quality = 95, bool alwaysProcess = false)
		{
			var relativeUrl = "{0}?width={1}&height={2}&crop={3}&quality={4}&alwaysProcess={5}".F(url, width, height, crop, quality, alwaysProcess);
			return relativeUrl;
		}

		public FileData Retrieve(string url, int width = 0, int height = 0, bool crop = false, int quality = 95, bool alwaysProcess = false)
		{
			var localFilePath = LocalFilePath(url, width, height, crop, quality, alwaysProcess);

			if (MustDownloadFile(localFilePath))
			{
				var remoteFileUrl = RemoteFileUrl(url, width, height, crop, quality, alwaysProcess);
				Download(remoteFileUrl, localFilePath);
			}

			return RetrieveFileFromFileSystem(localFilePath);
		}

		public void Save(string url, Stream file)
		{
			SaveInternal(url, file);
			Invalidate(url);
		}

		public void Delete(string url)
		{
			DeleteInternal(url);
			Invalidate(url);
		}

		public void Invalidate(string url)
		{
			var localFilePath = LocalFilePath(url);

			var fileExtension = Path.GetExtension(localFilePath);
			var fileFolder = Path.GetDirectoryName(localFilePath);
			var fileName = Path.GetFileNameWithoutExtension(localFilePath);
			var pattern = fileName + "*" + fileExtension;

			var directoryInfo = new DirectoryInfo(fileFolder);

			var files = directoryInfo.GetFiles(pattern, SearchOption.AllDirectories);
			foreach (var file in files)
			{
				if (file.Extension == ".metadata")
					continue;

				UpdateMetadata(file.FullName, m => m.IsDirty = true);
			}
		}

		public void InvalidateByPattern(string pattern)
		{
			var documentsDirectory = httpContext.Server.MapPath(FolderVirtualPath);
			var directoryInfo = new DirectoryInfo(documentsDirectory);
			var files = directoryInfo.GetFiles(pattern, SearchOption.AllDirectories);
			foreach (var file in files)
			{
				if (file.Extension == ".metadata")
					continue;

				UpdateMetadata(file.FullName, m => m.IsDirty = true);
			}
		}

		protected string LocalFilePath(string url, int width = 0, int height = 0, bool crop = false, int quality = 95, bool alwaysProcess = false)
		{
			url = "~/" + url.TrimStart('/');
			var directoryHash = VirtualPathUtility.GetDirectory(url).GetMD5Hash();
			var filename = VirtualPathUtility.GetFileName(url);
			var localFilePath = httpContext.Server.MapPath(FolderVirtualPath + directoryHash + "/" + filename);
			
			if (width != 0 && height != 0)
			{
				var fileExtension = Path.GetExtension(localFilePath);
				var fileFolder = Path.GetDirectoryName(localFilePath);
				var fileName = Path.GetFileNameWithoutExtension(localFilePath);

				fileName = "{0}-w{1}-h{2}-c{3}-q{4}{5}".F(fileName, width, height, crop ? 1 : 0, quality, fileExtension);
				localFilePath = Path.Combine(fileFolder, fileName);
			}

			return localFilePath;
		}

		protected string RemoteFileUrl(string url, int width = 0, int height = 0, bool crop = false, int quality = 95, bool alwaysProcess = false)
		{
			url = GetAbsoluteUrl(url);

			if (width != 0 && height != 0)
				url = "{0}?width={1}&height={2}&crop={3}&jpegquality={4}{5}".F(url, width, height, crop, quality, alwaysProcess ? "&alwaysprocess" : "");

			return url;
		}
	}
}